#!/usr/bin/env perl
use strict;
use warnings;
use diagnostics;
use Readonly;

use Test::MockObject;
use Test::More tests => 66;

use lib "$ENV{SKAL_ROOT}/lib";

Readonly(my @METHODS => (
    qw(new add del help list pass user_exists disconnect)
));

Readonly(my $HELP_MSG => <<END_OF_HELP_MSG);
Known actions / commands are:

add    - add new user and password
del    - delete existing user
help   - show this help message
list   - list all user names
pass   - set new password for existing user
END_OF_HELP_MSG

Readonly(my @INVALID_USER_NAMES => (
    'user name',
    'user__name',
    'user___name',
    'user____name',
    'user.name',
    'user..name',
    'user...name',
    'user....name',
    'user-name',
    'user--name',
    'user---name',
    'user----name',
    'user,name',
    'user?name',
    'user!name',
    'user"name',
    'user\'name',
    'user/name',
    'user\name',
    'user|name',
    'user€name',
    'user¶name',
    'user←name',
    'user↓name',
    'user→name',
    'userøname',
    'user@name',
    'user#name',
    'user$name',
    'user%name',
    'user§name',
    'user&name',
    'user*name',
    'user+name',
    'user=name',
    'user%name',
    'user`name',
    'user^name',
    'user{name',
    'user}name',
    'user(name',
    'user)name',
    'user[name',
    'user]name',
));

BEGIN { use_ok('Users'); }
# Testing Users Perl module

my $users;

my $mock_dbi = Test::MockObject->new;
my $mock_sth = Test::MockObject->new;

$mock_dbi->fake_module('DBI', connect => sub {
    return $mock_dbi;
});
$mock_dbi->set_always(prepare => $mock_sth);
$mock_dbi->set_true('disconnect');

$mock_sth->set_true('execute', 'finish');

foreach my $method (@METHODS) {
    can_ok(Users => $method);
}

ok($users = Users->new, 'New, connected');

isa_ok($users => 'Users');

ok(defined $users->{dbh}, 'Property dbh defined');

is($users->help, $HELP_MSG, 'Help message');

$mock_sth->set_always(fetchall_arrayref => []);

is($users->list, "There are no users in the database!\n", 'No users yet');

$mock_sth->set_always(fetchall_arrayref => [
    [ 'dan', ],
    [ 'inge', ],
    [ 'martin', ],
    [ 'petra', ],
]);

is(
    $users->list,
    "dan\ninge\nmartin\npetra\n-> Total number of users: 4\n",
    'List of users'
);

$mock_sth->set_always(fetchall_arrayref => [
    [ 'some_user_name', ],
]);

cmp_ok($users->user_exists('some_user_name'), '==', 1, 'User exists');

$mock_sth->set_always(fetchall_arrayref => [
    [ 'some_user2_name', ],
]);

cmp_ok($users->user_exists('some_user2_name'), '==', 1, 'User exists');

$mock_sth->set_always(fetchall_arrayref => []);

cmp_ok(
    $users->user_exists('user_name_which_does_not_exists'),
    '==',
    0,
    'User does not exist'
);

foreach my $invalid_user_name (@INVALID_USER_NAMES) {
    cmp_ok($users->user_exists($invalid_user_name), '==', -1, 'Invalid user name');
}

ok($users->disconnect, 'Disconnected');

$mock_dbi->set_always(do => 1);

cmp_ok(
    $users->add('some_user_name', 'some_user_password'),
    '==',
    1,
    'User added'
);

cmp_ok($users->del('some_user_name'), '==', 1, 'User deleted');

cmp_ok(
    $users->pass('some_user_name', 'some_user_new_password'),
    '==',
    1,
    'User password changed'
);

